package com.fpx.open.platform.service.impl;

import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Service;

import com.fpx.open.platform.common.constant.SysConstant;
import com.fpx.open.platform.common.util.DateUtil;
import com.fpx.open.platform.common.util.JsonBinder;
import com.fpx.open.platform.common.util.MD5Util;
import com.fpx.open.platform.dao.mapper0.WaybillMapper;
import com.fpx.open.platform.domain.ActionLog;
import com.fpx.open.platform.domain.ae.EventHeader;
import com.fpx.open.platform.domain.ae.response.Response;
import com.fpx.open.platform.domain.ae.response.ResponseItems;
import com.fpx.open.platform.domain.ae.response.Responses;
import com.fpx.open.platform.domain.ae.waybill.LogisticsWaybillEvent;
import com.fpx.open.platform.domain.ae.waybill.LogisticsWaybillRequest;
import com.fpx.open.platform.domain.ae.waybill.WaybillBody;
import com.fpx.open.platform.domain.exception.ServiceException;
import com.fpx.open.platform.service.ActionLogService;
import com.fpx.open.platform.service.WaybillService;

//@Service("waybillService")
public class WaybillServiceImpl implements WaybillService {

//    @Value(value = "${ae.url}")
    private String aeURL;

    @Value(value = "${ae.digest}")
    private String digest;

    @Resource
    private Jaxb2Marshaller jaxb2Marshaller;

    @Resource
    private ActionLogService actionLogService;

    @Resource
    private WaybillMapper waybillMapper;

    private static final String INTERFACE_NAME = "WAYBILLNO_UPLOAD";

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public synchronized void uploadWaybillNo(WaybillBody waybillBody) throws ServiceException {
        String xml = null;
        Responses responses = new Responses();
        try {
            LogisticsWaybillRequest request = new LogisticsWaybillRequest();
            LogisticsWaybillEvent logisticsWaybillEvent = new LogisticsWaybillEvent();
            EventHeader eventHeader = new EventHeader();
            eventHeader.setEventSource(waybillBody.getServiceCode());
            eventHeader.setEventTarget("taobao");
            eventHeader.setEventType("LOGISTICS_WAYBILL_UPLOAD");
            eventHeader.setEventTime(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));
            logisticsWaybillEvent.setEventHeader(eventHeader);
            Map<String, Object> paramMaps = new HashMap<String, Object>();
            //因暂时还不清楚阿里对于产品与仓库的划分，目前先硬编码实现
            paramMaps.put("productCode", "D1");
            paramMaps.put("waybillQuantity", waybillBody.getWaybillQuantity() + 1);
            List<String> waybillNoList = waybillMapper.queryWaybillNo(paramMaps);
            if (waybillNoList == null || waybillNoList.isEmpty()) {
                throw new ServiceException("queryWaybillNo error,because of have no waybillNo:" + paramMaps);
            }
            waybillBody.setWaybillList(waybillNoList);
            logisticsWaybillEvent.setWaybillBody(waybillBody);
            request.setLogisticsWaybillEvent(logisticsWaybillEvent);
            StringWriter sw = new StringWriter();
            StreamResult result = new StreamResult(sw);
            jaxb2Marshaller.marshal(request, result);
            xml = sw.toString();
            boolean deleteResult = deleteWaybillNo(waybillNoList);
            if(!deleteResult){
                throw new Exception("delete error");
            }
            String responseStr = postServer(aeURL, digest, xml,waybillBody.getWhCode());
            System.out.println("responseStr="+responseStr);
            Source source = new StreamSource(new StringReader(responseStr));
            responses = (Responses) jaxb2Marshaller.unmarshal(source);
            responses.getResponseItems().getResponse().setBizInfo(waybillBody.getMessageId());
        } catch (Exception e) {
            if (responses != null) {
                Response response = new Response();
                response.setSuccess(false);
                response.setErrorMsg(e.getMessage());
                response.setBizInfo(waybillBody.getMessageId());
                ResponseItems responseItems = new ResponseItems();
                responseItems.setResponse(response);
                responses.setResponseItems(responseItems);
            }
            logger.error(" uploadWaybillNo error:" + xml, e);
        } finally {
            logRequest(xml, responses, INTERFACE_NAME);
        }

    }

    private boolean deleteWaybillNo(List<String> waybillNoList) {
        String url = "jdbc:oracle:thin:@172.16.3.25:1522:orcle";
        String user = "svd";
        String password = "SvDPwd20120701";
//       String url = "jdbc:oracle:thin:@172.16.30.26:1521:xmstestd";
//       String user = "svd";
//       String password = "svd";
        Connection con = null;
        PreparedStatement ps = null;
        String sql = "DELETE FROM PDD_DOCUMENTCODEAVAILABLE PA WHERE PA.DC_CODE = ?";
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            con = DriverManager.getConnection(url, user, password);
            ps = con.prepareStatement(sql);
            if (waybillNoList != null && !waybillNoList.isEmpty()) {
                for (String wabyBill : waybillNoList) {
                    ps.setString(1, wabyBill);
                    ps.addBatch();
                }
                ps.executeBatch();
                con.commit();
            }
        } catch (Exception e) {
            logger.error(" deleteWaybillNo error:" + waybillNoList, e);
            return false;
        }finally{
            if(ps!=null){
                try {
                    ps.close();
                } catch (SQLException e) {
                }
            }
            if(con!=null){
                try {
                    con.close();
                } catch (SQLException e) {
                }
            }
        }
        return true;
    }

    // FIXME http请求部分可抽取为基础公共类，因工程依赖较多，暂时先如此实现功能
    private String postServer(String url, String digest, String xml,String warehouseCode) {
        Map<String, String> paraMaps = new HashMap<String, String>();
        paraMaps.put("logistics_interface", xml);
        paraMaps.put("msg_type", "B2B_WAYBILL");
        paraMaps.put("data_digest", MD5Util.Md5Base64(xml + digest));
        paraMaps.put("logistic_provider_id", warehouseCode);
        paraMaps.put("version", "2.1");
        try {
            String result = sendPostRequest(url, paraMaps);
            return result;
        } catch (Exception e) {
            logger.error(" invoke taobao uploadWaybillNo Service error:" + xml, e);
            return null;
        }
    }

    public String sendPostRequest(String url, Map<String, String> paras) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        for (Entry<String, String> entry : paras.entrySet()) {
            params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
        String result = sendRequest(httpPost, entity);
        return result;
    }

    private static String sendRequest(HttpEntityEnclosingRequestBase httpRequest, HttpEntity stringEntity)
            throws Exception {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        // httpRequest.setHeader(HttpHeaders.ACCEPT, "application/xml");
        httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=UTF-8");
        try {
            httpRequest.setEntity(stringEntity);
            HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 6000);
            HttpResponse response = httpClient.execute(httpRequest);
            HttpEntity httpEntity = response.getEntity();
            String result = EntityUtils.toString(httpEntity, "UTF-8");
            return result;
        } catch (Exception e) {
            throw new Exception("发送请求服务器端响应出错", e);
        } finally {
            if (httpRequest != null) {
                httpRequest.abort();
            }
            if (httpClient != null) {
                httpClient.getConnectionManager().shutdown();
            }
        }
    }

    private void logRequest(String request, Responses result, String interfaceName) throws ServiceException {
        ActionLog actionLog = new ActionLog();
        actionLog.setDateRequest(new Date());
        actionLog.setCustomerToken("no token");
        actionLog.setInterfaceName(interfaceName);
        actionLog.setReqContent(request);
        actionLog.setRespContent(JsonBinder.buildNonDefaultBinder().toJson(result));
        actionLog.setDateResponse(new Date());
        actionLog.setRemark(result.getResponseItems().getResponse().getBizInfo());
        if (result.getResponseItems().getResponse().isSuccess()) {
            actionLog.setStatus(SysConstant.STATUS_SUCCESS);
        } else {
            actionLog.setStatus(SysConstant.STATUS_FAILER);
        }
        actionLogService.saveActionLog(actionLog);
    }
}
